using System;
using System.Collections.Generic;
using System.Text;
using MediaPortal.GUI.Library;

namespace MyEmulators2
{
    public enum EmulatorType
    {
        manyemulators,
        pcgame
    }

    public class Emulator : DBItem, DBInterface
    {
        public Emulator() {}

        public Emulator(EmulatorType specialRole)
        {
            switch (specialRole)
            {
                case EmulatorType.pcgame:
                {
                    UID = -1; 
                    Title = Translator.getString(TranslatorString.pcgames); 
                    break;
                }
                case EmulatorType.manyemulators:
                {
                    UID = -2; 
                    break;
                }
            }
        }

        private int uid = -3;
        public int UID
        {
            get { return uid; }
            set { uid = value; }
        }

        private int grade = 0;
        public int Grade
        {
            get { return grade; }
            set { grade = value; }
        }


        private int yearmade = 0;
        public int Yearmade
        {
            get { return yearmade; }
            set { yearmade = value; }
        }

        private String description = "";
        public String Description
        {
            get { return description; }
            set { description = value; }
        }

        private String company = "";
        public String Company
        {
            get { return company; }
            set { company = value; }
        }

        private String pathToEmulator = "";
        public String PathToEmulator
        {
            get { return pathToEmulator; }
            set { pathToEmulator = value; }
        }

        private int position = 0;
        public int Position
        {
            get { return position; }
            set { position = value; }
        }

        private String pathToRoms = "";
        public String PathToRoms
        {
            get { return pathToRoms; }
            set { pathToRoms = value; }
        }

        private String title = "";
        public String Title
        {
            get { return title; }
            set { title = value; }
        }
        
        private String filter = "";
        public String Filter
        {
            get { return filter; }
            set { filter = value; }
        }

        private String workingFolder = "";
        public String WorkingFolder
        {
            get { return workingFolder; }
            set { workingFolder = value; }
        }
        
        private bool useQuotes = true;
        public bool UseQuotes
        {
            get { return useQuotes; }
            set { useQuotes = value; }
        }

        private bool suspendRendering = false;
        public bool SuspendRendering
        {
            get { return suspendRendering; }
            set { suspendRendering = value; }
        }

        private int view = 0;
        public int View
        {
            get { return view; }
            set { view = value; }
        }

        private bool enableGoodmerge = false;
        public bool EnableGoodmerge
        {
            get { return enableGoodmerge; }
            set { enableGoodmerge = value; }
        }

        private String goodmergePref1 = "";
        public String GoodmergePref1
        {
            get { return goodmergePref1; }
            set { goodmergePref1 = value; }
        }

        private String goodmergePref2 = "";
        public String GoodmergePref2
        {
            get { return goodmergePref2; }
            set { goodmergePref2 = value; }
        }

        private String goodmergePref3 = "";
        public String GoodmergePref3
        {
            get { return goodmergePref3; }
            set { goodmergePref3 = value; }
        }

        private String arguments = "";
        public String Arguments
        {
            get { return arguments; }
            set { arguments = value; }
        }

        bool mountImages = false; 
        public bool MountImages 
        {
            get { return mountImages; }
            set { mountImages = value; }
        }

        bool escapeToExit = false;
        public bool EscapeToExit
        {
            get { return escapeToExit; }
            set { escapeToExit = value; }
        }

        public bool isPc()
        {
            return UID == -1;
        }

        public bool isManyEmulators()
        {
            return UID == -2;
        }

        public override string ToString()
        {
            return Title;
        }

        public override ExtendedGUIListItem CreateGUIListItem()
        {
            ExtendedGUIListItem listItem = new ExtendedGUIListItem(title);
            listItem.AssociatedEmulator = this;

            using (ThumbGroup thumbs = new ThumbGroup(this))
                listItem.ThumbnailImage = thumbs.FrontCoverDefaultPath;

            return listItem;
        }

        public override void SetGUIProperties()
        {
            GUIPropertyManager.SetProperty("#item_title", this.Title);
            GUIPropertyManager.SetProperty("#emulator_title", "");
            GUIPropertyManager.SetProperty("#coverflow_label", "");
            GUIPropertyManager.SetProperty("#game_grade", this.Grade.ToString());
            //GUIPropertyManager.SetProperty("#fanartpath", ThumbsHandler.createEmulatorArt(this, "fanart"));
            GUIPropertyManager.SetProperty("#backcoverpath", "");
            GUIPropertyManager.SetProperty("#titlescreenpath", "");
            GUIPropertyManager.SetProperty("#ingamescreenpath", "");
            GUIPropertyManager.SetProperty("#game_yearmade", "");


            //displayStars(this.Grade);

            //displayDescriptionBackground(true);

            if (this.Yearmade > 0)
                GUIPropertyManager.SetProperty("#game_yearmade", this.Yearmade.ToString());

            GUIPropertyManager.SetProperty("#game_description", this.Description);
            GUIPropertyManager.SetProperty("#game_genre", "");
            GUIPropertyManager.SetProperty("#game_company", this.Company);
        }

        #region DBInterface Members

        public const string TABLE_NAME = "Emulators";

        const string TABLE_STRING =
            "uid int," +
            "emulator_path varchar(200)," +
            "position int," +
            "rom_path varchar(200)," +
            "title varchar(50)," +
            "filter varchar(100)," +
            "working_path varchar(200)," +
            "usequotes char(5)," +
            "view int," +
            "args varchar(200)," +
            "suspend_mp char(5)," +
            "enable_goodmerge char(5)," +
            "goodmerge_pref1 varchar(10)," +
            "goodmerge_pref2 varchar(10)," +
            "goodmerge_pref3 varchar(10)," +
            "Grade int," +
            "Company varchar(200)," +
            "Yearmade int," +
            "Description varchar(2000)," +
            "mountimages char(5)," +
            "escapetoexit char(5)," +
            "PRIMARY KEY(uid)";

        const string INSERT_STRING =
            "{0}," + //uid
            "'{1}'," + //path to emu
            "{2}," + //position
            "'{3}'," + //path to roms
            "'{4}'," + //title
            "'{5}'," + //filters
            "'{6}'," + //working dir
            "'{7}'," + //use quotes
            "{8}," + //default view
            "'{9}'," + //args
            "'{10}'," + //suspend rendering
            "'{11}'," + //enable goodmerge
            "'{12}'," + //goodpref 1
            "'{13}'," + //goodpref 2
            "'{14}'," + //goodpref 3
            "{15}," + //grade
            "'{16}'," + //company
            "{17}," + //year
            "'{18}'," + //description
            "'{19}'," + //mount images
            "'{20}'"; //escape to exit

        const string UPDATE_STRING =
            "emulator_path='{1}', " +
            "position={2}, " +
            "rom_path='{3}', " +
            "title='{4}', " +
            "filter='{5}', " +
            "working_path='{6}', " +
            "usequotes='{7}', " +
            "view={8}, " +
            "args='{9}', " +
            "suspend_mp='{10}', " +
            "enable_goodmerge='{11}', " +
            "goodmerge_pref1='{12}', " +
            "goodmerge_pref2='{13}', " +
            "goodmerge_pref3='{14}', " +
            "Grade={15}, " +
            "Company='{16}', " +
            "Yearmade={17}, " +
            "Description='{18}', " +
            "mountimages='{19}', " +
            "escapetoexit='{20}' " +
            "WHERE uid={0}";

        object[] DBParams
        {
            get
            {
                return new object[] 
                { 
                    uid, 
                    DB.Encode(pathToEmulator), 
                    position, 
                    DB.Encode(pathToRoms), 
                    DB.Encode(title), 
                    filter, 
                    DB.Encode(workingFolder), 
                    useQuotes, 
                    view, 
                    DB.Encode(arguments), 
                    suspendRendering, 
                    enableGoodmerge,  
                    goodmergePref1,
                    goodmergePref2,
                    goodmergePref3,
                    grade,
                    DB.Encode(company),
                    yearmade,
                    DB.Encode(description),
                    mountImages,
                    escapeToExit
                };
            }
        }

        public static Emulator CreateEmulator(SQLite.NET.SQLiteResultSet.Row sqlRow)
        {
            if (sqlRow.fields.Count != 21)
            {
                Logger.LogError("Unable to create Emulator, invalid database row");
                return null;
            }

            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.InvariantCulture;
            
            Emulator emu = new Emulator();
            emu.uid = int.Parse(sqlRow.fields[0], culture);
            emu.pathToEmulator = DB.Decode(sqlRow.fields[1]);
            emu.position = int.Parse(sqlRow.fields[2], culture);
            emu.pathToRoms = DB.Decode(sqlRow.fields[3]);
            emu.title = DB.Decode(sqlRow.fields[4]);
            emu.filter = sqlRow.fields[5];
            emu.workingFolder = DB.Decode(sqlRow.fields[6]);
            emu.useQuotes = bool.Parse(sqlRow.fields[7]);
            emu.view = int.Parse(sqlRow.fields[8], culture);
            emu.arguments = DB.Decode(sqlRow.fields[9]);
            emu.suspendRendering = bool.Parse(sqlRow.fields[10]);
            emu.enableGoodmerge = bool.Parse(sqlRow.fields[11]);
            emu.goodmergePref1 = sqlRow.fields[12];
            emu.goodmergePref2 = sqlRow.fields[13];
            emu.goodmergePref3 = sqlRow.fields[14];
            emu.grade = int.Parse(sqlRow.fields[15], culture);
            emu.company = DB.Decode(sqlRow.fields[16]);
            emu.yearmade = int.Parse(sqlRow.fields[17], culture);
            emu.description = DB.Decode(sqlRow.fields[18]);
            emu.mountImages = bool.Parse(sqlRow.fields[19]);
            emu.escapeToExit = bool.Parse(sqlRow.fields[20]);
            return emu;
        }

        public static Emulator GetPC()
        {
            Emulator emu = new Emulator(EmulatorType.pcgame);

            string title = Options.Instance.GetStringOption("pcitemtitle");
            if (title != "")
                emu.Title = title;

            emu.Company = Options.Instance.GetStringOption("pcitemcompany");
            emu.Description = Options.Instance.GetStringOption("pcitemdescription");
            emu.Yearmade = Options.Instance.GetIntOption("pcitemyear");
            emu.Grade = Options.Instance.GetIntOption("pcitemgrade");

            emu.Position = Options.Instance.GetIntOption("pcitemposition");

            return emu;
        }

        public static string DBTableString
        {
            get
            {
                return "CREATE TABLE " + TABLE_NAME + "(" + TABLE_STRING + ")";
            }
        }

        public string GetDBInsertString()
        {
            return "INSERT INTO " + TABLE_NAME + " VALUES(" + string.Format(System.Globalization.CultureInfo.InvariantCulture, INSERT_STRING, DBParams) + ")";
        }

        public string GetDBUpdateString()
        {
            return "UPDATE " + TABLE_NAME + " SET " + string.Format(System.Globalization.CultureInfo.InvariantCulture, UPDATE_STRING, DBParams);
        }

        public void Save()
        {
            if (uid == -1)
            {
                savePC();
                return;
            }

            lock (DB.Instance.SyncRoot)
            {
                if (Exists())
                {
                    DB.Instance.Execute(GetDBUpdateString());
                }
                else
                {
                    SQLite.NET.SQLiteResultSet result = DB.Instance.ExecuteWithoutLock("SELECT MAX(uid)+1 FROM {0}", TABLE_NAME);
                    if (result.Rows.Count > 0)
                        uid = MediaPortal.Database.DatabaseUtility.GetAsInt(result, 0, 0);
                    else
                        uid = 0;

                    DB.Instance.ExecuteWithoutLock(GetDBInsertString());
                }
            }
        }

        public void SavePosition()
        {
            if (uid < -1)
                return;

            if (uid == -1)
                Options.Instance.UpdateOption("pcitemposition", position);
            else
                DB.Instance.Execute("UPDATE {0} SET position={1} WHERE uid={2}", TABLE_NAME, position, uid);
        }

        void savePC()
        {
            if (uid != -1)
                return;

            Options.Instance.UpdateOption("pcitemtitle", title);
            Options.Instance.UpdateOption("pcitemcompany", company);
            Options.Instance.UpdateOption("pcitemdescription", description);
            Options.Instance.UpdateOption("pcitemyear", yearmade);
            Options.Instance.UpdateOption("pcitemgrade", grade);
            Options.Instance.UpdateOption("pcitemposition", position);
        }

        public void Delete()
        {
            if (uid < 0)
                return;

            lock (DB.Instance.SyncRoot)
            {
                DB.Instance.ExecuteWithoutLock("DELETE FROM {0} WHERE uid={1}", TABLE_NAME, uid);
                //remove any associated profiles
                DB.Instance.ExecuteWithoutLock("DELETE FROM {0} WHERE emulator_id={1}", EmulatorProfile.TABLE_NAME, uid);

                using (ThumbGroup thumbGroup = new ThumbGroup(this))
                {
                    try
                    {
                        if (System.IO.Directory.Exists(thumbGroup.ThumbPath))
                            System.IO.Directory.Delete(thumbGroup.ThumbPath, true);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError("Error deleting {0} thumb directory - {1}", this.title, ex.Message);
                    }
                }
            }
        }

        public bool Exists()
        {
            if (uid < -1)
                return false;

            return DB.Instance.Execute("SELECT 1 FROM {0} WHERE uid={1}", TABLE_NAME, uid).Rows.Count > 0;
        }

        #endregion
    }
}
